/*  Copyright (c) 2020 - ~, WANGXI
 *  
 *  NS CORE QUEUE EXPAND TEST MYFIFO CPP FILE
 * 
 *  Clone from https://gitee.com/WangXi_Chn/ns2_modulelib
 *  Note in https://www.yuque.com/wangxi_chn
 *  
 *  Change Logs:
 *  Date           Author       Notes			Mail
 *  2020-12-15     WangXi   	first version	WangXi_Chn@foxmail.com
*/

// 建立一个简单的drop-tail路由输出队列
// 该队列对优先的15个包使用循环出队法
// 其他的包依然保持在队列中

#include "dtrr_queue.h"

static class DtRrQueueClass:public TclClass
{
public:
    // DtRrQueue 对应的OTcl 的名称为Queue/DTRR
    DtRrQueueClass():TclClass("Queue/DTRR"){}
    TclObject* create(int,const char* const*){
        return (new DtRrQueue);
    }
}class_drop_tail_round_robin;

// 当Queue类中的recv的成员函数收到一个包时
// 它调用这个队列对象中的enqueue成员函数
// 如果链路对象没有阻塞，再调用 dequeue 成员函数
// 如果链路处于阻塞状态，仍然调用 dequeue 成员函数
// 因此需要重写 DtRrQueue 类的 enqueue 和 dequeue

void DtRrQueue::enque(Packet* p)
{
    hdr_ip* iph = hdr_ip::access(p);

    // 入队管理检查两个队列之和是否小于PQ允许的最大值
    // 如果小于，这个包可以入队到正常的逻辑队伍中

    //if IPv6 priority = 15 enqueue to queuel
    if (iph->prio_ == 15){
        q1_->enque(p);
        if ((q1_->length()+q2_->length())>qlim_)
        {
            q1_->remove(p);
            drop(p);
        }     
    }
    else{
        q2_->enque(p);
        if ((q1_->length()+q2_->length())>qlim_)
        {
            q2_->remove(p);
            drop(p);
        }
    }   
    
}


Packet* DtRrQueue::deque()
{
    Packet* p;

    // 出队管理试图从一个逻辑队列中让出一个包出列
    // 并且轮流从另一个逻辑队列中出下一个包
    // 在两个逻辑队列中都有包的情况下，两个逻辑队列是按照1：1的比率让包出队的

    if (deq_turn_ == 1){
        p = q1_->deque();
        if (p == 0){
            p = q2_->deque();
            deq_turn_ = 1;
        }
        else{
            deq_turn_ = 2;
        }
    }
    else
    {
        p = q2_->deque();
        if (p== 0){
            p = q1_->deque();
            deq_turn_ = 2;
        }
        else{
            deq_turn_ = 1;
        }
    }
    return(p);

}

// 在Makefile中的添加 queue/dtrr_queue.o
// （可通过查找drop-tail定位）[queue/queue.o queue/drop-tail.o queue/myfifo.o queue/dtrr_queue.o\]
// make 重新编译
// 没有错误后即可在tcl文件中使用该队列

// Now it can be used the same as DropTail

// #Create links between the nodes
// $ns duplex-link $n0 $n2 2Mb 10ms DropTail
// $ns duplex-link $n1 $n2 2Mb 10ms DTRR
// $ns duplex-link $n2 $n3 1.7Mb 20ms DropTail 


/************************ (C) COPYRIGHT 2020 WANGXI **************END OF FILE****/
